-module(gen_btree).

-include("btree.hrl").

%% API
-export([
    gen/0
    , do_gen/1
    , get_tree/1
    , set_tree/1
]).

%% 生成入口（所有组生成并存放到内存）
gen() ->
    GroupList = bnode_data:group_list(),
    lists:foreach(
        fun(Group) ->
            do_gen(Group)
        end,
        GroupList
    ),
    ok.

%% 按组生成单个
do_gen(Group) ->
    List = bnode_data:group_sort_list(Group),
    Nodes =
        lists:foldl(
            fun(Id, AccMap) ->
                gen_1(Group, Id, AccMap)
            end,
            #{},
            List
        ),
    Tree = tree(Group, Nodes),
    set_tree(Tree).

%% 将信息组合成单个节点
gen_1(Group, Id, NodeMap) ->
    DataList = bnode_data:group_data({Group, Id}),
    lists:foldl(
        fun({Parent, Children}, AccMap) ->
            AccMap1 =
                lists:foldl(
                    fun(Child, InAccMap1) ->
                        {Handler, Action} = bnode_data:node_data(Child),
                        Node = node(Child, Parent, Handler, Action),
                        maps:put(Child, Node, InAccMap1)
                    end,
                    AccMap,
                    Children
                ),
            %% 向父节点增加孩子
            case maps:get(Parent, AccMap, undef) of
                #bn{children = HaveChildren} = PBn ->
                    maps:put(Parent, PBn#bn{children = Children ++ HaveChildren}, AccMap1);
                _ ->
                    AccMap1
            end
        end,
        NodeMap,
        DataList
    ).

%% 生成#bn{}结构
node(Id, Parent, Handler, Action) ->
    #bn{
        id = Id, parent = Parent, handler = Handler,
        props = [{action, Action}], children = [], status = #{}
    }.

%% 生成#bt{}结构
tree(Group, Nodes) ->
    [{0, [Entry]}] = bnode_data:group_data({Group, 1}),
    #bt{
        group = Group,
        entry = Entry,
        nodes = Nodes,
        result = ?FAILURE,
        status = #{}
    }.

%% 保存树
set_tree(Tree) ->
    put(?tree_key(Tree#bt.group), Tree),
    Tree.

%% 获取树
get_tree(Group) ->
    get(?tree_key(Group)).